﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using TinyPMS_Jerusalem.Models.DBModel;
using TinyPMS_Jerusalem.ViewModels;

//IMPORTANT:Todo:检查用户名判断时的大小写问题，统一成都是小写时检查，即用户名不区分大小写

namespace TinyPMS_Jerusalem.Models
{

    #region 模型
    #endregion

    #region Services
    // FormsAuthentication 类型是密封的且包含静态成员，因此很难对
    // 调用其成员的代码进行单元测试。下面的接口和 Helper 类演示
    // 如何围绕这种类型创建一个抽象包装，以便可以对 AccountController
    // 代码进行单元测试。

    public interface IMembershipService
    {
        int MinPasswordLength { get; }

        bool ValidateUser(string userName, string password);
        MembershipCreateStatus CreateUser(string userName, string password, string email, bool IsApproved);
        bool ChangePassword(string userName, string oldPassword, string newPassword);
        bool CanRegister();
        bool IsUserApproved(string userName);
        void UpdateUserInfo(UserInfoModel model, string fillInfoLinkString);
        void CreateViewDataForDropList(out List<SelectListItem> genderListViewData);
        List<PendingUserModel> GetPendingUsers();
        UserInfoModel GetUserInfo(string userName);
        void DenyUser(string userName, bool deleteAllRelatedData);
    }

    public class AccountMembershipService : IMembershipService
    {
        private readonly MembershipProvider _provider;

        public AccountMembershipService()
            : this(null)
        {
        }

        public AccountMembershipService(MembershipProvider provider)
        {
            _provider = provider ?? Membership.Provider;
        }

        public int MinPasswordLength
        {
            get
            {
                return _provider.MinRequiredPasswordLength;
            }
        }

        public bool ValidateUser(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("值不能为 null 或为空。", "userName");
            if (String.IsNullOrEmpty(password)) throw new ArgumentException("值不能为 null 或为空。", "password");

            return _provider.ValidateUser(userName, password);
        }

        public MembershipCreateStatus CreateUser(string userName, string password, string email, bool IsApproved)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("值不能为 null 或为空。", "userName");
            if (String.IsNullOrEmpty(password)) throw new ArgumentException("值不能为 null 或为空。", "password");
            if (String.IsNullOrEmpty(email)) throw new ArgumentException("值不能为 null 或为空。", "email");

            MembershipCreateStatus status;
            _provider.CreateUser(userName, password, email, null, null, IsApproved, null, out status);
            return status;
        }

        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("值不能为 null 或为空。", "userName");
            if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("值不能为 null 或为空。", "oldPassword");
            if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("值不能为 null 或为空。", "newPassword");

            // 在某些出错情况下，基础 ChangePassword() 将引发异常，
            // 而不是返回 false。
            try
            {
                MembershipUser currentUser = _provider.GetUser(userName, true /* userIsOnline */);
                return currentUser.ChangePassword(oldPassword, newPassword);
            }
            catch (ArgumentException)
            {
                return false;
            }
            catch (MembershipPasswordException)
            {
                return false;
            }
        }
        /// <summary>
        /// 从数据库读取系统状态数据，判断当前系统是否允许新用户注册
        /// </summary>
        /// <returns>返回true表示允许注册，返回false表示不允许注册</returns>
        public bool CanRegister()
        {
            DBModelDataContext context = new DBModelDataContext();
            var query = from g in context.SystemState
                        where g.Name == "CanRegister"
                        select g;
            if (query.Single().State == "Yes")
                return true;
            else
                return false;
        }

        public bool IsUserApproved(string userName)
        {
            DBModelDataContext context = new DBModelDataContext();
            var query = from g in context.aspnet_Users
                        where g.LoweredUserName == userName.ToLower()
                        let userid = g.UserId
                        from c in context.aspnet_Membership
                        where c.UserId == userid
                        select c;
            if (query.Count() > 0)
            {
                return query.Single().IsApproved;
            }
            else
            {
                throw new ArgumentException("未找到用户");
            }
        }

        public void UpdateUserInfo(UserInfoModel model,string fillInfoLinkString)
        {
            Repository<UserInfo> infoRepository = new Repository<UserInfo>(new DBModelDataContext());
            UserInfo info= infoRepository.GetAll(c => c.FillInfoLinkString == fillInfoLinkString).Single();
            info.Address = model.Address;
            info.Gender = model.Gender;
            info.Name = model.Name;
            info.Phone = model.Phone;
            info.IsUserInfoFilled = true;
            infoRepository.Save();
        }


        public void CreateViewDataForDropList(out List<SelectListItem> genderListViewData)
        {
            genderListViewData = new List<SelectListItem>();
            genderListViewData.Add(new SelectListItem { Value = "False", Text = "男", Selected = false });
            genderListViewData.Add(new SelectListItem { Value = "True", Text = "女", Selected = false });
            genderListViewData[0].Selected = true;
        }

        public List<PendingUserModel> GetPendingUsers()
        {
            DBModelDataContext context = new DBModelDataContext();
            var query = from g in context.aspnet_Membership
                        where g.IsApproved == false
                        let userID = g.UserId
                        from c in context.aspnet_Users
                        where c.UserId == userID
                        select c;
            if (query.Count() <= 0)
                return null;
            else
            {
                List<aspnet_Users> usersList = query.ToList();
                List<PendingUserModel> result=new List<PendingUserModel>();
                foreach (aspnet_Users user in usersList)
                {
                    UserInfoModel info = GetUserInfo(user.LoweredUserName);
                    result.Add(new PendingUserModel { UserInfo = info, Email = user.aspnet_Membership.Email, UserName = user.UserName,UserID=user.UserId });
                }
                return result;
            }
        }

        public UserInfoModel GetUserInfo(string userName)
        {
            Repository<UserInfo> userInfoRepository = new Repository<UserInfo>(new DBModelDataContext());
            List<UserInfo> infos= userInfoRepository.GetAll(c => c.UserName.ToLower() == userName).ToList();
            if (infos.Count > 0)
            {
                UserInfo info = infos.Single();
                return new UserInfoModel { Address = info.Address, Gender = info.Gender, Name = info.Name, Phone = info.Phone };
            }
            else
            {
                throw new ArgumentException("未找到对应的用户");
            }
        }


        public void DenyUser(string userName, bool deleteAllRelatedData)
        {
            Repository<UserInfo> infoRepository = new Repository<UserInfo>(new DBModelDataContext());
            List<UserInfo> infoList=infoRepository.GetAll(c => c.UserName.ToLower() == userName.ToLower()).ToList();
            if (infoList.Count > 0)
            {
                infoRepository.Delete(infoList.Single());
                infoRepository.Save();
            }
            _provider.DeleteUser(userName, deleteAllRelatedData);
        }
    }

    public interface IFormsAuthenticationService
    {
        void SignIn(string userName, bool createPersistentCookie);
        void SignOut();
    }

    public class FormsAuthenticationService : IFormsAuthenticationService
    {
        public void SignIn(string userName, bool createPersistentCookie)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("值不能为 null 或为空。", "userName");
            FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
        }

        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
    #endregion


}
